package com.kuangjia.student_ems.controller;

import com.kuangjia.student_ems.dto.AttendanceDTO;
import com.kuangjia.student_ems.dto.AttendanceStatisticsDTO;
import com.kuangjia.student_ems.dto.UserDTO;
import com.kuangjia.student_ems.dto.request.AttendanceRequest;
import com.kuangjia.student_ems.dto.request.AttendanceLocationRequest;
import com.kuangjia.student_ems.service.AttendanceService;
import com.kuangjia.student_ems.service.UserService;
import com.kuangjia.student_ems.entity.Attendance;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.time.LocalDate;
import java.util.List;

@RestController
@RequestMapping("/attendances")
public class AttendanceController {

    @Autowired
    private AttendanceService attendanceService;
    
    @Autowired
    private UserService userService;

    @PostMapping("/clock-in")
    public ResponseEntity<AttendanceDTO> clockIn() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        UserDTO user = userService.getUserByUsername(username);
        return new ResponseEntity<>(attendanceService.clockIn(user.getId()), HttpStatus.CREATED);
    }

    @PostMapping("/clock-out")
    public ResponseEntity<AttendanceDTO> clockOut() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        UserDTO user = userService.getUserByUsername(username);
        return ResponseEntity.ok(attendanceService.clockOut(user.getId()));
    }
    
    @PostMapping("/clock-in-with-location")
    public ResponseEntity<AttendanceDTO> clockInWithLocation(@RequestBody AttendanceLocationRequest request) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        UserDTO user = userService.getUserByUsername(username);
        return new ResponseEntity<>(attendanceService.clockInWithLocation(user.getId(), request), HttpStatus.CREATED);
    }
    
    @PostMapping("/clock-out-with-location")
    public ResponseEntity<AttendanceDTO> clockOutWithLocation(@RequestBody AttendanceLocationRequest request) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        UserDTO user = userService.getUserByUsername(username);
        return new ResponseEntity<>(attendanceService.clockOutWithLocation(user.getId(), request), HttpStatus.CREATED);
    }
    
    @PostMapping
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public ResponseEntity<AttendanceDTO> createAttendance(
            @RequestParam Long userId,
            @Valid @RequestBody AttendanceRequest request) {
        return new ResponseEntity<>(attendanceService.createAttendance(userId, request), HttpStatus.CREATED);
    }
    
    @PutMapping("/{id}")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public ResponseEntity<AttendanceDTO> updateAttendance(
            @PathVariable Long id,
            @Valid @RequestBody AttendanceRequest request) {
        return ResponseEntity.ok(attendanceService.updateAttendance(id, request));
    }
    
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('HR_ADMIN')")
    public ResponseEntity<Void> deleteAttendance(@PathVariable Long id) {
        attendanceService.deleteAttendance(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @GetMapping("/my")
    public ResponseEntity<List<AttendanceDTO>> getMyAttendances(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        UserDTO user = userService.getUserByUsername(username);
        
        if (startDate != null && endDate != null) {
            return ResponseEntity.ok(attendanceService.getAttendancesByUserAndDateRange(user.getId(), startDate, endDate));
        } else {
            return ResponseEntity.ok(attendanceService.getAttendancesByUser(user.getId()));
        }
    }

    @GetMapping("/user/{userId}")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public ResponseEntity<List<AttendanceDTO>> getUserAttendances(
            @PathVariable Long userId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        if (startDate != null && endDate != null) {
            return ResponseEntity.ok(attendanceService.getAttendancesByUserAndDateRange(userId, startDate, endDate));
        } else {
            return ResponseEntity.ok(attendanceService.getAttendancesByUser(userId));
        }
    }

    @GetMapping("/department/{departmentId}")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public ResponseEntity<List<AttendanceDTO>> getDepartmentAttendances(
            @PathVariable Long departmentId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        return ResponseEntity.ok(attendanceService.getAttendancesByDepartmentAndDateRange(departmentId, startDate, endDate));
    }

    @GetMapping("/statistics/user/{userId}")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER') or #userId == authentication.principal.id")
    public ResponseEntity<AttendanceStatisticsDTO> getUserAttendanceStatistics(
            @PathVariable Long userId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        return ResponseEntity.ok(attendanceService.getUserAttendanceStatistics(userId, startDate, endDate));
    }

    @GetMapping("/statistics/department/{departmentId}")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public ResponseEntity<List<AttendanceStatisticsDTO>> getDepartmentAttendanceStatistics(
            @PathVariable Long departmentId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        return ResponseEntity.ok(attendanceService.getDepartmentAttendanceStatistics(departmentId, startDate, endDate));
    }

    @GetMapping
    @PreAuthorize("hasRole('HR_ADMIN')")
    public ResponseEntity<List<AttendanceDTO>> getAllAttendances() {
        return ResponseEntity.ok(attendanceService.getAllAttendances());
    }
    
    @GetMapping("/search")
    @PreAuthorize("hasRole('HR_ADMIN')")
    public ResponseEntity<List<AttendanceDTO>> searchAttendances(@RequestParam String keyword) {
        return ResponseEntity.ok(attendanceService.searchAttendances(keyword));
    }
    
    @GetMapping("/page")
    @PreAuthorize("hasAnyRole('HR_ADMIN', 'DEPARTMENT_MANAGER')")
    public IPage<AttendanceDTO> getAttendancePage(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) Long userId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(required = false, defaultValue = "date") String sortField,
            @RequestParam(required = false, defaultValue = "desc") String sortOrder) {
        try {
            if (pageNum < 1) pageNum = 1;
            if (pageSize < 1) pageSize = 10;
            Page<Attendance> page = new Page<>(pageNum, pageSize);
            return attendanceService.getAttendancePage(page, keyword, userId, startDate, endDate, sortField, sortOrder);
        } catch (Exception e) {
            e.printStackTrace();
            Page<AttendanceDTO> emptyPage = new Page<>();
            emptyPage.setRecords(java.util.Collections.emptyList());
            emptyPage.setTotal(0);
            return emptyPage;
        }
    }
} 